﻿using Cms.Application;
using Cms.Application.IO;
using Cms.Application.WebFramework.Presenters;
using Cms.Application.WebFramework.Views;
using Cms.Domain;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Cms.Tests.Unit.Application.WebFramework.Presenters
{
    [TestClass]
    public class MediaHandlerPresenterTests : BasePresenterTests
    {
        private MediaHandlerPresenter _presenter;
        private Mock<IMediaHandlerView> _viewMock;

        [TestMethod]
        public void ProcessFile_FileDoesNotExist_401()
        {
            MediaFile mediaFile = new MediaFile() { Name = "logo.png", Size = 5189 };
            SetupNonExistingFile(mediaFile);
            _presenter.ProcessFile();
            _viewMock.Verify(m => m.SetStatusCode(401));
        }

        [TestMethod]
        public void ProcessFile_AccessDenied_401()
        {
            MediaFile mediaFile = new MediaFile() { Name = "logo.png", Size = 5189 };
            UserGroup members = new UserGroup();
            mediaFile.RequiredUserGroups.Add(members);
            SetupExistingFile(mediaFile);
            _presenter.ProcessFile();
            _viewMock.Verify(m => m.SetStatusCode(401));
        }

        [TestMethod]
        public void ProcessFile_UserLoggedInButNoMembershipInRequiredGroup_AccessDenied()
        {
            MediaFile mediaFile = new MediaFile() { Name = "logo.png", Size = 5189 };
            UserGroup members = new UserGroup();
            mediaFile.RequiredUserGroups.Add(members);
            User user = new User();
            SetupExistingFile(mediaFile);
            _viewMock.SetupGet(m => m.UserId).Returns(12);
            UserRepositoryMock.Setup(m => m.GetUser(12)).Returns(user);
            _presenter.ProcessFile();
            _viewMock.Verify(m => m.SetStatusCode(401));
        }

        [TestMethod]
        public void ProcessFile_EverythingOk_FileIsServed()
        {
            MediaFile mediaFile = new MediaFile() { Name = "logo.png", Extension = "png", Size = 5189 };
            SetupExistingFile(mediaFile);
            _presenter.ProcessFile();
            _viewMock.Verify(m => m.SetContentType("image/png"));
            _viewMock.Verify(m => m.InsertOutputCacheEntry());
            _viewMock.Verify(m => m.AddHeader("Content-Length", "5189"));
            _viewMock.Verify(m => m.WriteFileToResponse(mediaFile.GetVirtualPath()));
        }

        private void SetupExistingFile(MediaFile mediaFile)
        {
            Setup(mediaFile, true);
        }

        private void SetupNonExistingFile(MediaFile mediaFile)
        {
            Setup(mediaFile, false);
        }

        private void Setup(MediaFile mediaFile, bool fileExists)
        {
            base.InitRepositoryFactoryMock();
            Site site = new Site() { RootMediaFolder = "media" };
            mediaFile.Site = site;
            _viewMock = new Mock<IMediaHandlerView>();
            _viewMock.SetupGet(m => m.MediaFile).Returns(mediaFile);
            _viewMock.SetupGet(m => m.PhysicalFilePath).Returns("C:\\fredium\\" + mediaFile.GetVirtualPath().Replace("/", "\\"));
            Mock<ICmsFileInfo> fileInfoMock = new Mock<ICmsFileInfo>();
            fileInfoMock.SetupGet(m => m.Exists).Returns(fileExists);
            fileInfoMock.SetupGet(m => m.Length).Returns(mediaFile.Size);
            Mock<IDiskAccess> diskAccessMock = new Mock<IDiskAccess>();
            diskAccessMock.Setup(m => m.GetFileInfo(It.IsAny<string>())).Returns(fileInfoMock.Object);
            _presenter = new MediaHandlerPresenter(_viewMock.Object, FactoryMock.Object) { DiskAccess = diskAccessMock.Object };
        }
    }
}
